*! 1.3.0 NJC 20 Feb 2002 
* 1.2.0 NJC 9 Feb 2001 
* 1.1.0 NJC 23 Nov 1998
* works with strings: not obviously useful, but the generalisation is cheap
* bug fix if p small implies h of 0
* 1.0.0 NJC 18 Nov 1998
program def winsor, sortpreserve 
        version 7.0
        syntax varname [if] [in] /* 
	*/ , Generate(str) [ H(int 0) P(real 0) LOWonly HIGHonly ] 

        capture confirm new variable `generate'
	if _rc { 
		di as err "generate() should give new variable name"
		exit _rc
	}	
		
	if `h' == 0 & `p' == 0 {
                di as err "h() or p() option required, h( ) or p() > 0"
                exit 198
        }
        else if `h' > 0 & `p' > 0 {
                di as err "use either h() option or p() option"
                exit 198
        }
        else if `h' < 0 | `p' < 0 {
                di as err "invalid negative value"
                exit 198
        }

        if `p' >= 0.5 {
                di as err "p() too high"
                exit 198
        }
	
	marksample touse, strok
	qui count if `touse'
	if r(N) == 0 { error 2000 } 
        local use = r(N)
        local notuse = _N - `use'

	if "`lowonly'`highonly'" != "" { 
		local text = /*
		*/ cond("`lowonly'" != "", ", low only", ", high only")
	} 	
	
        if `p' > 0  {
                local h = int(`p' * `use')
                if `h' == 0 {
                        di as err "0 values to be Winsorized"
                        exit 198
                }
                local which "Winsorized fraction `p'`text'"
        }
        else local which "Winsorized extreme `h'`text'"

        if `h' >= (`use' / 2) {
                di as err "`h' values to be Winsorized, `use' in data"
                exit 198
        }

        sort `touse' `varlist'
        local type : type `varlist'
        qui gen `type' `generate' = `varlist' if `touse'

        if "`lowonly'" == "" { 
		* replace upper tail by highest acceptable value
		local hiacc = _N - `h'
		local hiaccp1 = `hiacc' + 1
		qui replace `generate' = `generate'[`hiacc'] in `hiaccp1'/l
	}

	if "`highonly'" == "" { 
	        * replace lower tail by lowest acceptable value
        	local loacc = `notuse' + `h' + 1
	        local loaccm1 = `loacc' - 1
        	local lowest = `notuse' + 1
	        qui replace `generate' = /* 
		*/ `generate'[`loacc'] in `lowest'/`loaccm1'
	}	

        local fmt : format `varlist'
        format `generate' `fmt'

        label var `generate' "`varlist', `which'"
end
